using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Forms.Integration;
using System.Windows.Documents;
using System.Windows.Navigation;
using System.Windows.Media;
using System.Reflection;
using Ricciolo.PaperBoy.UI.Interop;
using System.Windows.Input;
using System.Windows.Controls.Primitives;
using System.Windows.Media.Imaging;

namespace Ricciolo.PaperBoy.UI
{
    public class IETabControl : TabControl
    {

        public const string BlankTarget = "_blank";

        static IETabControl()
        {
            //EventManager.RegisterClassHandler(typeof(IETabControl), Hyperlink.RequestNavigateEvent, new RequestNavigateEventHandler(OnIETabControlRequestNavigate));
        }

        private static void OnIETabControlRequestNavigate(object s, RequestNavigateEventArgs e)
        {
            Hyperlink h = (Hyperlink)e.Source;
            DependencyObject p = h;
            // Find if hyperlink is child
            while (p != null)
            {
                if (p is FrameworkContentElement)
                    p = ((FrameworkContentElement)p).Parent;
                else if (p is FrameworkElement)
                    p = ((FrameworkElement)p).Parent;
                else
                    p = null;
                if (p is IETabControl)
                {
                    ((IETabControl)p).Navigate(e.Uri, e.Target);
                    break;
                }
            }
        }

        public void Navigate(Uri uri, String target)
        {
            IETabItem item = null;
            if (this.Items.Count <= 1 || target == BlankTarget)
            {
                item = CreateNewItem(target);
            }
            else
            {
                // Find tab based on target
                foreach (TabItem ieitem in this.Items)
                    if (ieitem is IETabItem && String.CompareOrdinal(((IETabItem)ieitem).Target, target) == 0)
                    {
                        item = (IETabItem)ieitem;
                        break;
                    }
                // If not exist create new
                if (item == null)
                    item = CreateNewItem(target);
            }

            // Navigate to page
            item.Navigate(uri);
        }

        private IETabItem CreateNewItem(string target)
        {
            IETabItem item = new IETabItem(target);
            item.BeginInit();
            item.EndInit();
            this.Items.Add(item);
            return item;
        }

    }

    public class IETabItem : TabItem
    {
        private string _target;
        private FramePlus _frame;

        public static RoutedUICommand CloseTabCommand = new RoutedUICommand("Close tab", "CloseTab", typeof(IETabItem));
        public static RoutedUICommand CloseOtherTabsCommand = new RoutedUICommand("Close other tabs", "CloseOtherTab", typeof(IETabItem));
        public static RoutedUICommand RefreshTabCommand = new RoutedUICommand("Refresh tab", "RefreshTab", typeof(IETabItem));

        static IETabItem()
        {
            CommandManager.RegisterClassCommandBinding(typeof(IETabItem), new CommandBinding(CloseTabCommand, new ExecutedRoutedEventHandler(OnCloseTabExecuted), new CanExecuteRoutedEventHandler(OnCloseTabCanExecute)));
            CommandManager.RegisterClassCommandBinding(typeof(IETabItem), new CommandBinding(CloseOtherTabsCommand, new ExecutedRoutedEventHandler(OnCloseOtherTabsExecuted), new CanExecuteRoutedEventHandler(OnCloseOtherTabsCanExecute)));
            CommandManager.RegisterClassCommandBinding(typeof(IETabItem), new CommandBinding(RefreshTabCommand, new ExecutedRoutedEventHandler(OnRefreshTabExecuted), new CanExecuteRoutedEventHandler(OnRefreshTabCanExecute)));
        }

        public IETabItem(string target)
        {
            this._target = target;

            _frame = new FramePlus();
            _frame.BeginInit();
            _frame.Padding = new Thickness(0d);
            _frame.JournalOwnership = JournalOwnership.OwnsJournal;
            _frame.NavigationUIVisibility = NavigationUIVisibility.Hidden;
            _frame.NavigationFailed += new NavigationFailedEventHandler(Frame_NavigationFailed);
            _frame.EndInit();
            this.Content = _frame;

            this.InputBindings.Add(new KeyBinding(CloseTabCommand, Key.W, ModifierKeys.Control));
            this.InputBindings.Add(new KeyBinding(RefreshTabCommand, Key.F5, ModifierKeys.None));

            this.IsSelected = true;
        }

        void Frame_NavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            e.Handled = true;

            // Navigate to page showing error
            NavigationErrorPage error = new NavigationErrorPage(e.Uri, e.Exception);
            this.Frame.Navigate(error);
        }

        #region Commands

        static void OnCloseTabExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            IETabItem tab = (IETabItem)sender;
            // Remove this item
            ItemsControl list = ItemsControl.ItemsControlFromItemContainer(tab);
            list.Items.Remove(tab);
        }

        static void OnCloseTabCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        static void OnRefreshTabExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            ((IETabItem)sender).Frame.Refresh();
        }

        static void OnRefreshTabCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        static void OnCloseOtherTabsExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            IETabItem tab = (IETabItem)sender;
            // Remove other items
            ItemsControl list = ItemsControl.ItemsControlFromItemContainer(tab);
            for (int x = 0; x < list.Items.Count; x++)
            {
                // Only IETabItem
                if (list.Items[x] is IETabItem && list.Items[x] != tab)
                {
                    list.Items.RemoveAt(x);
                    x--;
                }
            }
        }

        static void OnCloseOtherTabsCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        #endregion

        public FramePlus Frame
        {
            get { return this._frame; }
        }

        public string Target
        {
            get { return _target; }
        }

        public void Navigate(Uri uri)
        {
            _frame.StopLoading();
            try
            {
                _frame.Navigate(uri);
            }
            catch (NotSupportedException)
            {}
            this.IsSelected = true;
        }
    }

}
